#include "GdfPreCompile.h"

#include "GdfRoot.h"
#include "GdfWindow.h"
#include "GdfSceneManager.h"


// render system include
#if RENDER_SYSTEM_VER == 9
#	include "GdfDX9RenderSystem.h"
#elif RENDER_SYSTEM_VER == 10
#	include "GdfDX10RenderSystem.h"
#elif RENDER_SYSTEM_VER == 11
#	include "GdfDX11RenderSystem.h"
#endif


namespace Gdf
{
	GdfRoot::GdfRoot()
		:mWindowManager(NULL)
		,mRenderSystem(NULL)
		,mSceneManager(NULL)
		,mEndRendering(false)
	{
		mWindowManager = GDF_NEW GdfWindowManager;
	}

	GdfRoot::~GdfRoot()
	{
		GDF_DELETE(mWindowManager);
		GDF_DELETE(mRenderSystem);
		GDF_DELETE(mSceneManager);
	}

	bool GdfRoot::Initialize(GdfWindow* window)
	{
		// add windows
		AddWindow(window);

		// create render system
		#if RENDER_SYSTEM_VER == 9
		mRenderSystem = GDF_NEW GdfDX9RenderSystem(window->GetHwnd());
		if (!mRenderSystem->Initialize())
		{
			GDF_DELETE(mRenderSystem);
			return false;
		}
		#elif RENDER_SYSTEM_VER == 10
		#elif RENDER_SYSTEM_VER == 11
		#endif

		mSceneManager = GDF_NEW GdfSceneManager;

		return true;
	}

	void GdfRoot::Release()
	{
	}

	int GdfRoot::StartRendering()
	{
		int ret(0);
		float32 frameTime(0.0f);

		while (!mEndRendering)
		{
			// get tick time
			//frameTime = mTimer->GetLastTickTime();

			// window message pump
			mWindowManager->MessagePump();

			// tick
			PreUpdateFrame(frameTime);

			// render
			RenderFrame(frameTime);

			// tick
			PostUpdateFrame(frameTime);

			// check frame listener add
			if ( !mFrameListenerAddReserve.empty() )
			{
				while( !mFrameListenerAddReserve.empty() )
				{
					if ( mFrameListeners.end() == std::find( mFrameListeners.begin(), mFrameListeners.end(), mFrameListenerAddReserve.back() ) )
						mFrameListeners.push_back( mFrameListenerAddReserve.back() );
					mFrameListenerAddReserve.pop_back();
				}
			}

			// check frame listener del
			if ( !mFrameListenerDelReserve.empty() )
			{
				while( !mFrameListenerDelReserve.empty() )
				{
					mFrameListeners.erase( std::remove( mFrameListeners.begin(), mFrameListeners.end(), mFrameListenerDelReserve.back() ), mFrameListeners.end() );
					//FrameListenerList::iterator it = std::find( mFrameListeners.begin(), mFrameListeners.end(), mFrameListenerDelReserve.back() );
					//if ( it != mFrameListeners.end() )
					//	mFrameListeners.erase( it );
					mFrameListenerDelReserve.pop_back();
				}
			}
		}

		return ret;
	}

	void GdfRoot::PreUpdateFrame(const float32 frameTime)
	{
		for ( FrameListenerList::iterator it = mFrameListeners.begin(), end = mFrameListeners.end(); it != end; ++it )
		{
			(*it)->PreUpdateFrame(frameTime);
		}
	}

	void GdfRoot::RenderFrame(const float32 frameTime)
	{
		mRenderSystem->RequestRender();
	}

	void GdfRoot::PostUpdateFrame(const float32 frameTime)
	{
		for ( FrameListenerList::iterator it = mFrameListeners.begin(), end = mFrameListeners.end(); it != end; ++it )
		{
			(*it)->PostUpdateFrame(frameTime);
		}
	}

	void GdfRoot::AddWindow(GdfWindow* window)
	{
		if ( mWindowManager )
			mWindowManager->AddWindow(window);
	}

	void GdfRoot::AddFrameListener(GdfFrameListener* listner)
	{
		mFrameListenerAddReserve.push_back(listner);
	}

	void GdfRoot::DelFrameListener(GdfFrameListener* listner)
	{
		mFrameListenerDelReserve.push_back(listner);
	}

}
